package com.yict.csms.system.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.yict.common.service.impl.BaseServiceImpl;
import com.yict.common.util.ObjectUtil;
import com.yict.csms.system.dao.IDataDictDao;
import com.yict.csms.system.entity.DataDict;
import com.yict.csms.system.service.IDataDictService;
import com.yict.csms.system.util.DictionaryUtils;

@Service("dataDictService")
public class DataDictServiceImpl extends
		BaseServiceImpl<DataDict, String, IDataDictDao> implements
		IDataDictService {

	// 实现一个缓冲池
	private Map<String, List<DataDict>> typeMap = new LinkedHashMap<String, List<DataDict>>();
	private final static int MAX_TYPEMAP_SIZE = 100;

	@Override
	public List<DataDict> queryByType(String type) {
		List<DataDict> list = null;
		//list = typeMap.get(type);
		if (list == null || list.size() == 0) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("datatype", type);
			LinkedHashMap<String, Boolean> order = new LinkedHashMap<String, Boolean>();
			order.put("datacode", true);
			order.put("datavalue", true);
			list = this.list(map, null, order);
			//this.addTypeMap(type, list);
		}
		return list;
	}
	
	/**
	 * 根据code查找一个字典，没找到返回null
	 * @param code
	 * @return
	 */
	public DataDict findByCode(String code){
		DataDict vo = null;
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("datacode", code);
		List<DataDict> list = this.list(map, null, null);
		if(list.size() > 0) vo = list.get(0);
		return vo;
	}
	
	/**
	 * 根据displayname和datatype查找一个字典，没找到返回null
	 * @param name
	 * @param type
	 * @return
	 */
	public DataDict findByName(String name,String type){
		DataDict vo = null;
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("datatype", type);
		map.put("displayname", name);
		List<DataDict> list = this.list(map, null, null);
		if(list.size() > 0) vo = list.get(0);
		return vo;
	}
	
	public List<DataDict> getAll() {
		Map<String,Object> map = new HashMap<String,Object>();
		LinkedHashMap<String,Boolean> order = new LinkedHashMap<String,Boolean>();
		order.put("dictid", true);
		return this.list(map, null, order);
	}
	
	public HashMap<String, String> getDisplayMap() {
		List<DataDict> dataDicts = getAll();
		HashMap<String, String> dataDictMap = new HashMap<String, String>();
		for (DataDict dataDict : dataDicts) {
			dataDictMap.put(dataDict.getDictid(), dataDict.getDisplayname());
		}
		return dataDictMap;
	}

	public LinkedHashMap<String, String> getShipCompanyMap() {
		LinkedHashMap<String, String> shipCompany = new LinkedHashMap<String, String>();
		List<DataDict> list = queryByType("ship_company");
		for (DataDict dataDict : list) {
			shipCompany.put(dataDict.getDictid(), dataDict.getDisplayname());
		}
		return shipCompany;
	}
	
	/**
	 * 获取指定日期的更次
	 * @param date
	 * @return
	 */
	@Override
	public DataDict findShiftTime(Date date){
		String hql = "from DataDict t where t.datatype=:datatype order by t.datavalue";
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("datatype", DictionaryUtils.DICT_TYPE_TIME_BUCKET);
		List<DataDict> shiftTimes = getBaseDao().list(hql,map, 0, 0);
		
		DataDict dict = null;
		Calendar from = Calendar .getInstance(); 
		Calendar to = Calendar .getInstance(); 
		from.setTime(date);
		to.setTime(date);
		for(DataDict d : shiftTimes){
			String timeRange = d.getDatavalue();
			String[] fromTo = timeRange.split("-");
			String[] fromFields = fromTo[0].split(":");
			String[] toFields = fromTo[1].split(":");
			from.set(Calendar.HOUR_OF_DAY, ObjectUtil.s2i(fromFields[0]));
			from.set(Calendar.MINUTE, ObjectUtil.s2i(fromFields[1]));
			from.set(Calendar.SECOND, ObjectUtil.s2i(fromFields[2]));
			to.set(Calendar.HOUR_OF_DAY, ObjectUtil.s2i(toFields[0]));
			to.set(Calendar.MINUTE, ObjectUtil.s2i(toFields[1]));
			to.set(Calendar.SECOND, ObjectUtil.s2i(toFields[2]));
			if(date.compareTo(from.getTime()) >= 0 && date.compareTo(to.getTime()) <= 0){
				dict = d;
				break;
			}
		}
		return dict;
	}
	
	/**
	 * 获取指定更次的开始时间
	 * @param dict 更次
	 * @param date 返还时间的年月日，如果为null则为当前时间
	 * @return
	 */
	public Date getShiftStartTime(DataDict dict,Date date)throws Exception{
		Date stDate;
		if(dict == null || !DictionaryUtils.DICT_TYPE_TIME_BUCKET.equals(dict.getDatatype())) return null;
		if(date == null) date = new Date();
		try {
			String timeRange = dict.getDatavalue();
			String[] fromTo = timeRange.split("-");
			String[] fromFields = fromTo[0].split(":");
			//String[] toFields = fromTo[1].split(":");
			Calendar from = Calendar .getInstance(); 
			from.setTime(date);
			from.set(Calendar.HOUR_OF_DAY, ObjectUtil.s2i(fromFields[0]));
			from.set(Calendar.MINUTE, ObjectUtil.s2i(fromFields[1]));
			from.set(Calendar.SECOND, ObjectUtil.s2i(fromFields[2]));
			from.set(Calendar.MILLISECOND, 0);
			stDate = from.getTime();
		} catch (Exception e) {
			throw new Exception("查询更次字典出错");
		}
		return stDate;
	}
	
	/**
	 * 获取指定日期的下一更次
	 * @param date
	 * @param cycle true 则对于一天的最后一更时间返回第一更，否则返回null值
	 * @return
	 */
	@Override
	public DataDict findNextShiftTime(Date date,boolean cycle){
		String hql = "from DataDict t where t.datatype=:datatype order by t.datavalue";
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("datatype", DictionaryUtils.DICT_TYPE_TIME_BUCKET);
		List<DataDict> shiftTimes = getBaseDao().list(hql,map, 0, 0);
		
		DataDict dict = null;
		Calendar from = Calendar .getInstance(); 
		Calendar to = Calendar .getInstance(); 
		from.setTime(date);
		to.setTime(date);
		int next = 0;
		for(DataDict d : shiftTimes){
			next += 1;
			String timeRange = d.getDatavalue();
			String[] fromTo = timeRange.split("-");
			String[] fromFields = fromTo[0].split(":");
			String[] toFields = fromTo[1].split(":");
			from.set(Calendar.HOUR_OF_DAY, ObjectUtil.s2i(fromFields[0]));
			from.set(Calendar.MINUTE, ObjectUtil.s2i(fromFields[1]));
			from.set(Calendar.SECOND, ObjectUtil.s2i(fromFields[2]));
			to.set(Calendar.HOUR_OF_DAY, ObjectUtil.s2i(toFields[0]));
			to.set(Calendar.MINUTE, ObjectUtil.s2i(toFields[1]));
			to.set(Calendar.SECOND, ObjectUtil.s2i(toFields[2]));
			if(date.compareTo(from.getTime()) >= 0 && date.compareTo(to.getTime()) <= 0){
				break;
			}
		}
		if(next < shiftTimes.size()) 
			dict = shiftTimes.get(next);
		else{
			if(cycle) dict = shiftTimes.get(0);
		}
		
		return dict;
	}
	
	@Override
	@Transactional(readOnly = false)
	public boolean save(DataDict t) throws Exception {
		typeMap.remove(t.getDatatype());
		return super.save(t);
	}

	@Override
	@Transactional(readOnly = false)
	public boolean update(DataDict t) throws Exception {
		typeMap.remove(t.getDatatype());
		return super.update(t);
	}

	@Override
	@Transactional(readOnly = false)
	public boolean remove(DataDict t) throws Exception {
		typeMap.remove(t.getDatatype());
		return super.remove(t);
	}

	@Override
	@Transactional(readOnly = false)
	public boolean remove(String[] ids) throws Exception {
		for(String id :ids){
			DataDict t = this.findById(id);
			this.remove(t);
		}
		return true;
	}

	private void addTypeMap(String type, List<DataDict> list) {
		List<String> oldKey = new ArrayList<String>();
		// 保持不超过MAX_TYPEMAP_SIZE个类型项
		int maxSize = MAX_TYPEMAP_SIZE - 1;
		if (typeMap.size() > maxSize) {
			Set<Entry<String, List<DataDict>>> set = typeMap.entrySet();
			for (Entry<String, List<DataDict>> entry : set) {
				oldKey.add(entry.getKey());
			}
			for (int i = maxSize; i < oldKey.size(); i++) {
				typeMap.remove(typeMap.get(i));
			}
		}
		typeMap.put(type, list);
	}
	
	/**
	 * 
	 * @param type
	 * @return
	 */
	public LinkedHashMap<String,String> queryDictMap(String type){
		LinkedHashMap<String,String> dictMap = new LinkedHashMap<String, String>();
		List<DataDict> list = this.queryByType(type);
		for(DataDict t : list){
			dictMap.put(t.getDictid(), t.getDisplayname());
		}
		return dictMap;
	}

	public Map<String, List<DataDict>> getTypeMap() {
		return typeMap;
	}

	public void setTypeMap(Map<String, List<DataDict>> typeMap) {
		this.typeMap = typeMap;
	}

	@Resource(name = "dataDictDao")
	public void setBaseDao(IDataDictDao baseDao) {
		super.setBaseDao(baseDao);
	}
}
